#ifndef _XPLMMap_h_
#define _XPLMMap_h_

/*
 * Copyright 2005-2012 Sandy Barbour and Ben Supnik
 * 
 * All rights reserved.  See license.txt for usage.
 * 
 * X-Plane SDK Version: 2.1.1                                                  
 *
 */

/*
 * This API allows you to create new layers within X-Plane maps. Your layers 
 * can draw arbitrary OpenGL, but they conveniently also have access to 
 * X-Plane's built-in icon and label drawing functions. 
 * 
 * As of X-Plane 11, map drawing happens in three stages: 
 * 
 * 1. backgrounds and "fill," 2. icons, and 3. labels. 
 * 
 * Thus, all background drawing gets layered beneath all icons, which likewise 
 * get layered beneath all labels. Within each stage, the map obeys a 
 * consistent layer ordering, such that "fill" layers (layers that cover a 
 * large amount of map area, like the terrain and clouds) appear beneath 
 * "markings" layers (like airport icons). This ensures that layers with fine 
 * details don't get obscured by layers with larger details. 
 * 
 * The XPLM map API reflects both aspects of this draw layering: you can 
 * register a layer as providing either markings or fill, and X-Plane will 
 * draw your fill layers beneath your markings layers (regardless of 
 * registration order). Likewise, you are guaranteed that your layer's icons 
 * (added from within an icon callback) will go above your layer's OpenGL 
 * drawing, and your labels will go above your icons. 
 * 
 * The XPLM guarantees that all plugin-created fill layers go on top of all 
 * native X-Plane fill layers, and all plugin-created markings layers go on 
 * top of all X-Plane markings layers (with the exception of the aircraft 
 * icons). It also guarantees that the draw order of your own plugin's layers 
 * will be consistent. But, for layers created by different plugins, the only 
 * guarantee is that we will draw all of one plugin's layers of each type 
 * (fill, then markings), then all of the others'; we don't guarantee which 
 * plugin's fill and markings layers go on top of the other's. 
 * 
 * As of X-Plane 11, maps use true cartographic projections for their drawing, 
 * and different maps may use different projections. For that reason, all 
 * drawing calls include an opaque handle for the projection you should use to 
 * do the drawing. Any time you would draw at a particular latitude/longitude, 
 * you'll need to ask the projection to translate that position into "map 
 * coordinates." (Note that the projection is guaranteed not to change between 
 * calls to your prepare-cache hook, so if you cache your map coordinates 
 * ahead of time, there's no need to re-project them when you actually draw.) 
 * 
 * In addition to mapping normal latitude/longitude locations into map 
 * coordinates, the projection APIs also let you know the current heading for 
 * north. (Since X-Plane 11 maps can rotate to match the heading of the user's 
 * aircraft, it's not safe to assume that north is at zero degrees rotation.)  
 *
 */

#include "XPLMDefs.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(XPLM300)
/***************************************************************************
 * DRAWING CALLBACKS
 ***************************************************************************/
/*
 * When you create a new map layer (using XPLMCreateMapLayer), you can provide 
 * any or all of these callbacks. They allow you to insert your own OpenGL 
 * drawing, text labels, and icons into the X-Plane map at the appropriate 
 * places, allowing your layer to behave as similarly to X-Plane's built-in 
 * layers as possible.                                                         
 *
 */


/*
 * XPLMMapLayerID
 * 
 * This is an opaque handle for a plugin-created map layer. Pass it to the map 
 * drawing APIs from an appropriate callback to draw in the layer you created. 
 *
 */
typedef void * XPLMMapLayerID;

/*
 * XPLMMapProjectionID
 * 
 * This is an opaque handle for a map projection. Pass it to the projection 
 * APIs to translate between map coordinates and latitude/longitudes.          
 *
 */
typedef void * XPLMMapProjectionID;

/*
 * XPLMMapStyle
 * 
 * Indicates the visual style being drawn by the map. In X-Plane, the user can 
 * choose between a number of map types, and different map types may have use 
 * a different visual representation for the same elements (for instance, the 
 * visual style of the terrain layer changes drastically between the VFR and 
 * IFR layers), or certain layers may be disabled entirely in some map types 
 * (e.g., localizers are only visible in the IFR low-enroute style).           
 *
 */
enum {
     xplm_MapStyle_VFR_Sectional              = 0

    ,xplm_MapStyle_IFR_LowEnroute             = 1

    ,xplm_MapStyle_IFR_HighEnroute            = 2


};
typedef int XPLMMapStyle;

/*
 * XPLMMapDrawingCallback_f
 * 
 * This is the OpenGL map drawing callback for plugin-created map layers. You 
 * can perform arbitrary OpenGL drawing from this callback, with one 
 * exception: changes to the Z-buffer are not permitted, and will result in 
 * map drawing errors. 
 * 
 * All drawing done from within this callback appears beneath all built-in 
 * X-Plane icons and labels, but above the built-in "fill" layers (layers 
 * providing major details, like terrain and water). Note, however, that the 
 * relative ordering between the drawing callbacks of different plugins is not 
 * guaranteed.                                                                 
 *
 */
typedef void (* XPLMMapDrawingCallback_f)(
                                   XPLMMapLayerID       inLayer,    
                                   const float *        inMapBoundsLeftTopRightBottom,    
                                   float                zoomRatio,    
                                   float                mapUnitsPerUserInterfaceUnit,    
                                   XPLMMapStyle         mapStyle,    
                                   XPLMMapProjectionID  projection,    
                                   void *               inRefcon);    

/*
 * XPLMMapIconDrawingCallback_f
 * 
 * This is the icon drawing callback that enables plugin-created map layers to 
 * draw icons using X-Plane's built-in icon drawing functionality. You can 
 * request an arbitrary number of PNG icons to be drawn via 
 * XPLMDrawMapIconFromSheet() from within this callback, but you may not 
 * perform any OpenGL drawing here. 
 * 
 * Icons enqueued by this function will appear above all OpenGL drawing 
 * (performed by your optional XPLMMapDrawingCallback_f), and above all 
 * built-in X-Plane map icons of the same layer type ("fill" or "markings," as 
 * determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, 
 * however, that the relative ordering between the drawing callbacks of 
 * different plugins is not guaranteed.                                        
 *
 */
typedef void (* XPLMMapIconDrawingCallback_f)(
                                   XPLMMapLayerID       inLayer,    
                                   const float *        inMapBoundsLeftTopRightBottom,    
                                   float                zoomRatio,    
                                   float                mapUnitsPerUserInterfaceUnit,    
                                   XPLMMapStyle         mapStyle,    
                                   XPLMMapProjectionID  projection,    
                                   void *               inRefcon);    

/*
 * XPLMMapLabelDrawingCallback_f
 * 
 * This is the label drawing callback that enables plugin-created map layers 
 * to draw text labels using X-Plane's built-in labeling functionality. You 
 * can request an arbitrary number of text labels to be drawn via 
 * XPLMDrawMapLabel() from within this callback, but you may not perform any 
 * OpenGL drawing here. 
 * 
 * Labels enqueued by this function will appear above all OpenGL drawing 
 * (performed by your optional XPLMMapDrawingCallback_f), and above all 
 * built-in map icons and labels of the same layer type ("fill" or "markings," 
 * as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, 
 * however, that the relative ordering between the drawing callbacks of 
 * different plugins is not guaranteed.                                        
 *
 */
typedef void (* XPLMMapLabelDrawingCallback_f)(
                                   XPLMMapLayerID       inLayer,    
                                   const float *        inMapBoundsLeftTopRightBottom,    
                                   float                zoomRatio,    
                                   float                mapUnitsPerUserInterfaceUnit,    
                                   XPLMMapStyle         mapStyle,    
                                   XPLMMapProjectionID  projection,    
                                   void *               inRefcon);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * LAYER MANAGEMENT CALLBACKS
 ***************************************************************************/
/*
 * These are various "bookkeeping" callbacks that your map layer can receive 
 * (if you provide the callback in your XPLMCreateMapLayer_t). They allow you 
 * to manage the lifecycle of your layer, as well as cache any 
 * computationally-intensive preparation you might need for drawing.           
 *
 */


/*
 * XPLMMapPrepareCacheCallback_f
 * 
 * A callback used to allow you to cache whatever information your layer needs 
 * to draw in the current map area. 
 * 
 * This is called each time the map's total bounds change. This is typically 
 * triggered by new DSFs being loaded, such that X-Plane discards old, 
 * now-distant DSFs and pulls in new ones. At that point, the available bounds 
 * of the map also change to match the new DSF area. 
 * 
 * By caching just the information you need to draw in this area, your future 
 * draw calls can be made faster, since you'll be able to simply "splat" your 
 * precomputed information each frame. 
 * 
 * We guarantee that the map projection will not change between successive 
 * prepare cache calls, nor will any draw call give you bounds outside these 
 * total map bounds. So, if you cache the projected map coordinates of all the 
 * items you might want to draw in the total map area, you can be guaranteed 
 * that no draw call will be asked to do any new work.                         
 *
 */
typedef void (* XPLMMapPrepareCacheCallback_f)(
                                   XPLMMapLayerID       inLayer,    
                                   const float *        inTotalMapBoundsLeftTopRightBottom,    
                                   XPLMMapProjectionID  projection,    
                                   void *               inRefcon);    

/*
 * XPLMMapWillBeDeletedCallback_f
 * 
 * Called just before your map layer gets deleted. Because SDK-created map 
 * layers have the same lifetime as the X-Plane map that contains them, if the 
 * map gets unloaded from memory, your layer will too.                         
 *
 */
typedef void (* XPLMMapWillBeDeletedCallback_f)(
                                   XPLMMapLayerID       inLayer,    
                                   void *               inRefcon);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP LAYER CREATION AND DESTRUCTION
 ***************************************************************************/
/*
 * Enables the creation of new map layers. Layers are created for a particular 
 * instance of the X-Plane map. For instance, if you want your layer to appear 
 * in both the normal map interface and the Instructor Operator Station (IOS), 
 * you would need two separate calls to XPLMCreateMapLayer(), with two 
 * different values for your XPLMCreateMapLayer_t::layer_name. 
 * 
 * Your layer's lifetime will be determined by the lifetime of the map it is 
 * created in. If the map is destroyed (on the X-Plane side), your layer will 
 * be too, and you'll receive a callback to your 
 * XPLMMapWillBeDeletedCallback_f.                                             
 *
 */


/*
 * XPLMMapLayerType
 * 
 * Indicates the type of map layer you are creating. Fill layers will always 
 * be drawn beneath markings layers.                                           
 *
 */
enum {
     /* A layer that draws "fill" graphics, like weather patterns, terrain, etc.    *
      * Fill layers frequently cover a large portion of the visible map area.       */
     xplm_MapLayer_Fill                       = 0

     /* A layer that provides markings for particular map features, like NAVAIDs,   *
      * airports, etc. Even dense markings layers cover a small portion of the      *
      * total map area.                                                             */
    ,xplm_MapLayer_Markings                   = 1


};
typedef int XPLMMapLayerType;

/* Globally unique identifier for X-Plane's Map window, used as the            *
 * mapToCreateLayerIn parameter in XPLMCreateMapLayer_t                        */
#define XPLM_MAP_USER_INTERFACE "XPLM_MAP_USER_INTERFACE"

/* Globally unique identifier for X-Plane's Instructor Operator Station        *
 * window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t    */
#define XPLM_MAP_IOS         "XPLM_MAP_IOS"

/*
 * XPLMCreateMapLayer_t
 * 
 * This structure defines all of the parameters used to create a map layer 
 * using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs 
 * to include more features.  Always set the structSize member to the size of 
 * your struct in bytes! 
 * 
 * Each layer must be associated with exactly one map instance in X-Plane. 
 * That map, and that map alone, will call your callbacks. Likewise, when that 
 * map is deleted, your layer will be as well.                                 
 *
 */
typedef struct {
     /* Used to inform XPLMCreateMapLayer() of the SDK version you compiled         *
      * against; should always be set to sizeof(XPLMCreateMapLayer_t)               */
     int                       structSize;
     /* Globally unique string identifying the map you want this layer to appear    *
      * in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or     *
      * XPLM_MAP_IOS                                                                */
     const char *              mapToCreateLayerIn;
     /* The type of layer you are creating, used to determine draw order (all       *
      * plugin-created markings layers are drawn above all plugin-created fill      *
      * layers)                                                                     */
     XPLMMapLayerType          layerType;
     /* Optional callback to inform you this layer is being deleted (due to its     *
      * owning map being destroyed)                                                 */
     XPLMMapWillBeDeletedCallback_f willBeDeletedCallback;
     /* Optional callback you want to use to prepare your draw cache when the map   *
      * bounds change (set to NULL if you don't want this callback)                 */
     XPLMMapPrepareCacheCallback_f prepCacheCallback;
     /* Optional callback you want to use for arbitrary OpenGL drawing, which goes  *
      * beneath all icons in the map's layering system (set to NULL if you don't    *
      * want this callback)                                                         */
     XPLMMapDrawingCallback_f  drawCallback;
     /* Optional callback you want to use for drawing icons, which go above all     *
      * built-in X-Plane icons (except the aircraft) in the map's layering system   *
      * (set to NULL if you don't want this callback)                               */
     XPLMMapIconDrawingCallback_f iconCallback;
     /* Optional callback you want to use for drawing map labels, which go above    *
      * all built-in X-Plane icons and labels (except those of aircraft) in the     *
      * map's layering system (set to NULL if you don't want this callback)         */
     XPLMMapLabelDrawingCallback_f labelCallback;
     /* True if you want a checkbox to be created in the map UI to toggle this      *
      * layer on and off; false if the layer should simply always be enabled        */
     int                       showUiToggle;
     /* Short label to use for this layer in the user interface                     */
     const char *              layerName;
     /* A reference to arbitrary data that will be passed to your callbacks         */
     void *                    refcon;
} XPLMCreateMapLayer_t;

/*
 * XPLMCreateMapLayer
 * 
 * This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t 
 * structure with all of the fields set in.  You must set the structSize of 
 * the structure to the size of the actual structure you used. 
 * 
 * Returns NULL if the layer creation failed. This happens most frequently 
 * because the map you specified in your 
 * XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if 
 * XPLMMapExists() returns 0 for the specified map). You can use 
 * XPLMRegisterMapCreationHook() to get a notification each time a new map is 
 * opened in X-Plane, at which time you can create layers in it.               
 *
 */
XPLM_API XPLMMapLayerID       XPLMCreateMapLayer(
                                   XPLMCreateMapLayer_t * inParams);    

/*
 * XPLMDestroyMapLayer
 * 
 * Destroys a map layer you created (calling your 
 * XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion 
 * took place.                                                                 
 *
 */
XPLM_API int                  XPLMDestroyMapLayer(
                                   XPLMMapLayerID       inLayer);    

/*
 * XPLMMapCreatedCallback_f
 * 
 * A callback to notify your plugin that a new map has been created in 
 * X-Plane. This is the best time to add a custom map layer using 
 * XPLMCreateMapLayer(). 
 * 
 * No OpenGL drawing is permitted within this callback.                        
 *
 */
typedef void (* XPLMMapCreatedCallback_f)(
                                   const char *         mapIdentifier,    
                                   void *               refcon);    

/*
 * XPLMRegisterMapCreationHook
 * 
 * Registers your callback to receive a notification each time a new map is 
 * constructed in X-Plane. This callback is the best time to add your custom 
 * map layer using XPLMCreateMapLayer(). 
 * 
 * Note that you will not be notified about any maps that already exist---you 
 * can use XPLMMapExists() to check for maps that were created previously.     
 *
 */
XPLM_API void                 XPLMRegisterMapCreationHook(
                                   XPLMMapCreatedCallback_f callback,    
                                   void *               refcon);    

/*
 * XPLMMapExists
 * 
 * Returns 1 if the map with the specified identifier already exists in 
 * X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying 
 * that your layer should be added to that map.                                
 *
 */
XPLM_API int                  XPLMMapExists(
                                   const char *         mapIdentifier);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP DRAWING
 ***************************************************************************/
/*
 * These APIs are only valid from within a map drawing callback (one of 
 * XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing 
 * callbacks are registered when you create a new map layer as part of your 
 * XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map 
 * drawing functionality for icons and labels, so that you get a consistent 
 * style with the rest of the X-Plane map. 
 * 
 * Note that the X-Plane 11 map introduces a strict ordering: layers of type 
 * xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers. 
 * Likewise, all OpenGL drawing (performed in your layer's 
 * XPLMMapDrawingCallback_f) will appear beneath any icons and labels you 
 * draw.                                                                       
 *
 */


/*
 * XPLMMapOrientation
 * 
 * Indicates whether a map element should be match its rotation to the map 
 * itself, or to the user interface. For instance, the map itself may be 
 * rotated such that "up" matches the user's aircraft, but you may want to 
 * draw a text label such that it is always rotated zero degrees relative to 
 * the user's perspective. In that case, you would have it draw with UI 
 * orientation.                                                                
 *
 */
enum {
     /* Orient such that a 0 degree rotation matches the map's north                */
     xplm_MapOrientation_Map                  = 0

     /* Orient such that a 0 degree rotation is "up" relative to the user interface */
    ,xplm_MapOrientation_UI                   = 1


};
typedef int XPLMMapOrientation;

/*
 * XPLMDrawMapIconFromSheet
 * 
 * Enables plugin-created map layers to draw PNG icons using X-Plane's 
 * built-in icon drawing functionality. Only valid from within an 
 * XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons 
 * to be drawn from within your callback). 
 * 
 * X-Plane will automatically manage the memory for your texture so that it 
 * only has to be loaded from disk once as long as you continue drawing it 
 * per-frame. (When you stop drawing it, the memory may purged in a "garbage 
 * collection" pass, require a load from disk in the future.) 
 * 
 * Instead of having X-Plane draw a full PNG, this method allows you to use UV 
 * coordinates to request a portion of the image to be drawn. This allows you 
 * to use a single texture load (of an icon sheet, for example) to draw many 
 * icons. Doing so is much more efficient than drawing a dozen different small 
 * PNGs. 
 * 
 * The UV coordinates used here treat the texture you load as being comprised 
 * of a number of identically sized "cells." You specify the width and height 
 * in cells (ds and dt, respectively), as well as the coordinates within the 
 * cell grid for the sub-image you'd like to draw. 
 * 
 * Note that you can use different ds and dt values in subsequent calls with 
 * the same texture sheet. This enables you to use icons of different sizes in 
 * the same sheet if you arrange them properly in the PNG. 
 * 
 * This function is only valid from within an XPLMIconDrawingCallback_t (but 
 * you can request an arbitrary number of icons to be drawn from within your 
 * callback).                                                                  
 *
 */
XPLM_API void                 XPLMDrawMapIconFromSheet(
                                   XPLMMapLayerID       layer,    
                                   const char *         inPngPath,    
                                   int                  s,    
                                   int                  t,    
                                   int                  ds,    
                                   int                  dt,    
                                   float                mapX,    
                                   float                mapY,    
                                   XPLMMapOrientation   orientation,    
                                   float                rotationDegrees,    
                                   float                mapWidth);    

/*
 * XPLMDrawMapLabel
 * 
 * Enables plugin-created map layers to draw text labels using X-Plane's 
 * built-in labeling functionality. Only valid from within an 
 * XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of 
 * text labels to be drawn from within your callback).                         
 *
 */
XPLM_API void                 XPLMDrawMapLabel(
                                   XPLMMapLayerID       layer,    
                                   const char *         inText,    
                                   float                mapX,    
                                   float                mapY,    
                                   XPLMMapOrientation   orientation,    
                                   float                rotationDegrees);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP PROJECTIONS
 ***************************************************************************/
/*
 * As of X-Plane 11, the map draws using true cartographic projections, and 
 * different maps may use different projections. Thus, to draw at a particular 
 * latitude and longitude, you must first transform your real-world 
 * coordinates into map coordinates. 
 * 
 * The map projection is also responsible for giving you the current scale of 
 * the map. That is, the projection can tell you how many map units correspond 
 * to 1 meter at a given point. 
 * 
 * Finally, the map projection can give you the current rotation of the map. 
 * Since X-Plane 11 maps can rotate to match the heading of the aircraft, the 
 * map's rotation can potentially change every frame.                          
 *
 */


/*
 * XPLMMapProject
 * 
 * Projects a latitude/longitude into map coordinates. This is the inverse of 
 * XPLMMapUnproject(). 
 * 
 * Only valid from within a map layer callback (one of 
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, 
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)            
 *
 */
XPLM_API void                 XPLMMapProject(
                                   XPLMMapProjectionID  projection,    
                                   double               latitude,    
                                   double               longitude,    
                                   float *              outX,    
                                   float *              outY);    

/*
 * XPLMMapUnproject
 * 
 * Transforms map coordinates back into a latitude and longitude. This is the 
 * inverse of XPLMMapProject(). 
 * 
 * Only valid from within a map layer callback (one of 
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, 
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)            
 *
 */
XPLM_API void                 XPLMMapUnproject(
                                   XPLMMapProjectionID  projection,    
                                   float                mapX,    
                                   float                mapY,    
                                   double *             outLatitude,    
                                   double *             outLongitude);    

/*
 * XPLMMapScaleMeter
 * 
 * Returns the number of map units that correspond to a distance of one meter 
 * at a given set of map coordinates. 
 * 
 * Only valid from within a map layer callback (one of 
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, 
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)            
 *
 */
XPLM_API float                XPLMMapScaleMeter(
                                   XPLMMapProjectionID  projection,    
                                   float                mapX,    
                                   float                mapY);    

/*
 * XPLMMapGetNorthHeading
 * 
 * Returns the heading (in degrees clockwise from "up") that corresponds to 
 * north at a given point on the map. In other words, if your runway has a 
 * true heading of 360, you would use "north" as the Cartesian angle at which 
 * to draw the runway on the map. (You would add the result of 
 * XPLMMapGetNorthHeading() to your true heading to get the map angle.) 
 * 
 * This is necessary becuase X-Plane's map can be rotated to match your 
 * aircraft's orientation; north is not always "up." 
 * 
 * Only valid from within a map layer callback (one of 
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, 
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)            
 *
 */
XPLM_API float                XPLMMapGetNorthHeading(
                                   XPLMMapProjectionID  projection,    
                                   float                mapX,    
                                   float                mapY);    

#endif /* XPLM300 */
#ifdef __cplusplus
}
#endif

#endif
